using Circus.CodeEditor;
using Circus.CodeEditor.Serialization;
using Circus.CodeEditor.TextSource;
using Circus.Syntax;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
namespace Circus.CodeEditor
{
	public class Outlining {
		internal class DisplayRange : OutlineRange
		{
			private Outlining.OutlineList owner;
			public override bool Visible
			{
				get
				{
					return base.Visible;
				}
				set
				{
					if (base.Visible != value)
					{
						base.Visible = value;
						if (this.owner != null)
						{
							this.owner.UpdateRange(this, true);
						}
					}
				}
			}
			public override string DisplayText
			{
				get
				{
					return (this.owner != null && (this.owner.Owner.OutlineOptions & OutlineOptions.DrawButtons) == OutlineOptions.None) ? string.Empty : this.Text;
				}
			}
			public DisplayRange()
			{
			}
			public DisplayRange(Outlining.OutlineList owner, Point startPt, Point endPt, int level, string text) : base(startPt, endPt, level, text)
			{
				this.owner = owner;
			}
			public DisplayRange(Outlining.OutlineList owner, Point startPt, Point endPt, int level, string text, bool visible) : base(startPt, endPt, level, text, visible)
			{
				this.owner = owner;
			}
		}
	
		internal class CollapsedRange : Outlining.DisplayRange, ICloneable
		{
			private int deltaX = 0;
			private int deltaY = 0;
			public int DeltaX
			{
				get
				{
					return this.deltaX;
				}
			}
			public int DeltaY
			{
				get
				{
					return this.deltaY;
				}
			}
			public CollapsedRange(Outlining.OutlineList owner, Point startPt, Point endPt, int deltaX, int deltaY, int level, string text) : base(owner, startPt, endPt, level, text)
			{
				this.deltaX = deltaX;
				this.deltaY = deltaY;
			}
		}
		internal class CollapsedList : RangeList2
		{
			private class RealComparer : IComparer<Range>
			{
				public int Compare(Range x, Range y)
				{
					Point endPoint = x.EndPoint;
					Point startPoint = y.StartPoint;
					int result;
					if (startPoint.Y < endPoint.Y || (startPoint.Y == endPoint.Y && startPoint.X < endPoint.X))
					{
						result = 1;
					}
					else
					{
						result = 0;
					}
					return result;
				}
			}
			private class DisplayComparer : IComparer<Range>
			{
				public int Compare(Range x, Range y)
				{
					Outlining.CollapsedRange collapsedRange = ((SortRange)x).Range as Outlining.CollapsedRange;
					int num = collapsedRange.EndPoint.Y + collapsedRange.DeltaY;
					int num2 = collapsedRange.EndPoint.X + collapsedRange.DeltaX - (collapsedRange.DisplayText.Length - 1);
					Point startPoint = y.StartPoint;
					int result;
					if (startPoint.Y < num || (startPoint.Y == num && startPoint.X < num2))
					{
						result = 1;
					}
					else
					{
						result = 0;
					}
					return result;
				}
			}
			private int collapsedCount;
			private IComparer<Range> realComparer;
			private IComparer<Range> displayComparer;
			public int CollapsedCount
			{
				get
				{
					return this.collapsedCount;
				}
				set
				{
					this.collapsedCount = value;
				}
			}
			public CollapsedList()
			{
				this.realComparer = new Outlining.CollapsedList.RealComparer();
				this.displayComparer = new Outlining.CollapsedList.DisplayComparer();
			}
			public override bool UpdatePosition(Range range, int x, int y, int deltaX, int deltaY)
			{
				int num = range.EndPoint.X - range.StartPoint.X;
				int num2 = range.EndPoint.Y - range.StartPoint.Y;
				return base.UpdatePosition(range, x, y, deltaX, deltaY) && (range.EndPoint.X - range.StartPoint.X != num || range.EndPoint.Y - range.StartPoint.Y != num2);
			}
			public new int Add(Range value)
			{
				int num = base.Add(value);
				base.TopRange.Add(new SortRange(value, num));
				return num;
			}
			public void GetRealPoint(ref Point point, bool rangeStart)
			{
				Outlining.CollapsedRange collapsedRange = base.FindRange(point, this.displayComparer) as Outlining.CollapsedRange;
				if (collapsedRange != null)
				{
					int num = collapsedRange.EndPoint.Y + collapsedRange.DeltaY;
					int num2 = collapsedRange.EndPoint.X + collapsedRange.DeltaX;
					if (point.Y == num && point.X != int.MaxValue)
					{
						int num3 = num2;
						if (point.X < num3 && rangeStart)
						{
							point.X = num3 - collapsedRange.DisplayText.Length;
							point.Y = collapsedRange.StartPoint.Y;
							return;
						}
						if (point.X < num3)
						{
							point.X = num3;
						}
						point.X += collapsedRange.EndPoint.X - num3;
					}
					if (point.Y != int.MaxValue)
					{
						point.Y += collapsedRange.EndPoint.Y - num;
					}
				}
			}
			public void GetDisplayPoint(ref Point point)
			{
				Outlining.CollapsedRange collapsedRange = base.FindRange(point, this.realComparer) as Outlining.CollapsedRange;
				if (collapsedRange != null)
				{
					if (point.Y == collapsedRange.EndPoint.Y && point.X != int.MaxValue)
					{
						point.X += collapsedRange.DeltaX;
					}
					if (point.Y != int.MaxValue)
					{
						point.Y += collapsedRange.DeltaY;
					}
				}
			}
		}
		internal class OutlineList : RangeList2
		{
			private Outlining.CollapsedList collapsedList;
			private DisplayStrings owner;
			public DisplayStrings Owner
			{
				get
				{
					return this.owner;
				}
			}
			public IList<Range> CollapsedList
			{
				get
				{
					return this.collapsedList;
				}
			}
			public int CollapsedCount
			{
				get
				{
					return this.collapsedList.CollapsedCount;
				}
			}
			public OutlineList(DisplayStrings owner)
			{
				this.owner = owner;
				this.collapsedList = new Outlining.CollapsedList();
			}
			public void CollapseChanged(OutlineRange range)
			{
				int first = 0;
				int last = int.MaxValue;
				if (this.owner.WordWrap)
				{
					if (range != null)
					{
						first = range.StartPoint.Y;
						if (range.StartPoint.Y == range.EndPoint.Y)
						{
							last = range.EndPoint.Y;
						}
						this.owner.UpdateWordWrap(range.StartPoint.Y, int.MaxValue);
					}
					else
					{
						this.owner.UpdateWordWrap(0, int.MaxValue);
					}
				}
				this.owner.UpdateNeeded();
				this.owner.Notify(NotifyState.Outline, first, last);
			}
			public override bool BlockDeleting(Rectangle rect)
			{
				bool flag = base.BlockDeleting(rect);
				if (flag)
				{
					this.UpdateRange(null, false);
				}
				return flag;
			}
			public override bool PositionChanged(int x, int y, int deltaX, int deltaY)
			{
				bool flag = base.PositionChanged(x, y, deltaX, deltaY);
				if (flag)
				{
					if (this.collapsedList.PositionChanged(x, y, deltaX, deltaY))
					{
						this.UpdateRange(null, false);
					}
				}
				return flag;
			}
			public bool IsVisible(Point point)
			{
				return this.collapsedList.FindRange(point) == null;
			}
			public bool IsVisible(int index)
			{
				return this.collapsedList.FindInclusiveRange(index) == null;
			}
			public void CheckVisible(ref int index)
			{
				Range range = this.collapsedList.FindInclusiveRange(index);
				if (range != null)
				{
					index = range.StartPoint.Y;
				}
			}
			public new void Clear()
			{
				base.Clear();
				this.collapsedList.Clear();
				this.UpdateRange(null, true);
			}
			public override void Update()
			{
				base.Update();
				this.UpdateRange(null, true);
			}
			public void UpdateRange(OutlineRange rng, bool update)
			{
				if (base.UpdateCount <= 0)
				{
					Point point = Point.Empty;
					int num = 0;
					int num2 = 0;
					this.collapsedList.Clear();
					int count = this.owner.Lines.Count;
					this.collapsedList.BeginUpdate();
					try
					{
						using (List<Range>.Enumerator enumerator = base.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								OutlineRange outlineRange = (OutlineRange)enumerator.Current;
								if (!outlineRange.Visible && !outlineRange.IsEmpty && this.IsVisible(outlineRange.StartPoint))
								{
									num2 += Math.Min(outlineRange.EndPoint.Y, count - 1) - Math.Min(outlineRange.StartPoint.Y, count - 1);
									if (outlineRange.StartPoint.Y != point.Y)
									{
										num = 0;
									}
									num += outlineRange.EndPoint.X - outlineRange.StartPoint.X - outlineRange.DisplayText.Length;
									this.collapsedList.Add(new Outlining.CollapsedRange(null, outlineRange.StartPoint, outlineRange.EndPoint, -num, -num2, 0, outlineRange.DisplayText));
									point = outlineRange.EndPoint;
								}
							}
						}
					}
					finally
					{
						this.collapsedList.EndUpdate();
					}
					this.collapsedList.CollapsedCount = num2;
					if (update)
					{
						this.CollapseChanged(rng);
					}
				}
			}
			public void GetRealPoint(ref Point point, bool rangeStart)
			{
				this.collapsedList.GetRealPoint(ref point, rangeStart);
			}
			public void GetDisplayPoint(ref Point point)
			{
				Range range = this.collapsedList.FindRange(point);
				if (range != null)
				{
					point = range.StartPoint;
				}
				this.collapsedList.GetDisplayPoint(ref point);
			}
			public Range FindCollapsedRange(Point point)
			{
				return this.collapsedList.FindExactRange(point);
			}
			public int GetCollapsedRanges(int index, IList<Range> ranges)
			{
				return this.collapsedList.GetExactRanges(ranges, index);
			}
			public int LineToDisplayLine(int index)
			{
				Point point = new Point(0, index);
				this.GetDisplayPoint(ref point);
				return point.Y;
			}
			public int DisplayLineToLine(int index)
			{
				Point point = new Point(0, index);
				this.GetRealPoint(ref point, false);
				return point.Y;
			}
		}
		private Color outlineColor = EditConsts.DefaultOutlineForeColor;
		private bool useRoundRect = true;
		private int imageSize = EditConsts.DefaultCollasedImageWidth;
		private CodeEditor owner;
		private DisplayStrings displayLines;
		[Browsable(false)]
		public event OutlineEvent Expanding
		{
			add
			{
				if (this.displayLines != null)
				{
					this.displayLines.Expanding += value;
				}
			}
			remove
			{
				if (this.displayLines != null)
				{
					this.displayLines.Expanding -= value;
				}
			}
		}
		[Browsable(false)]
		public event OutlineEvent Collapsing
		{
			add
			{
				if (this.displayLines != null)
				{
					this.displayLines.Collapsing += value;
				}
			}
			remove
			{
				if (this.displayLines != null)
				{
					this.displayLines.Collapsing -= value;
				}
			}
		}
		protected virtual int UpdateCount
		{
			get
			{
				return (this.displayLines != null) ? this.displayLines.UpdateCount : 0;
			}
		}
		[Description("Gets or sets color that is used to draw outline button.")]
		public virtual Color OutlineColor
		{
			get
			{
				return this.outlineColor;
			}
			set
			{
				if (this.outlineColor != value)
				{
					this.outlineColor = value;
					this.OnOutlineColorChanged();
				}
			}
		}
		[DefaultValue(true)]
		public bool UseRoundRect
		{
			get
			{
				return this.useRoundRect;
			}
			set
			{
				if (this.useRoundRect != value)
				{
					this.useRoundRect = value;
					this.OnUseRoundRectChanged();
				}
			}
		}
		public int ImageSize
		{
			get
			{
				return this.imageSize;
			}
			set
			{
				if (this.imageSize != value)
				{
					this.imageSize = value;
					this.OnImageSizeChanged();
				}
			}
		}
		
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public virtual int CollapsedCount
		{
			get
			{
				return (this.displayLines != null) ? this.displayLines.CollapsedCount : 0;
			}
		}
		[DefaultValue(false), Description("Gets or sets a value indicating whether outlining enabled.")]
		public virtual bool AllowOutlining
		{
			get
			{
				return this.displayLines != null && this.displayLines.AllowOutlining;
			}
			set
			{
				if (this.displayLines != null)
				{
					this.displayLines.AllowOutlining = value;
				}
			}
		}
		[Category("SyntaxEdit"), Description("Gets or sets outlining options."), Editor("QWhale.Design.FlagEnumerationEditor, QWhale.Design", typeof(UITypeEditor))]
		public virtual OutlineOptions OutlineOptions
		{
			get
			{
				return (this.displayLines != null) ? this.displayLines.OutlineOptions : OutlineOptions.None;
			}
			set
			{
				if (this.displayLines != null)
				{
					this.displayLines.OutlineOptions = value;
				}
			}
		}
		protected virtual void OnOutlineColorChanged()
		{
			if (this.owner != null && this.AllowOutlining)
			{
				this.owner.Invalidate();
			}
		}
		protected virtual void OnUseRoundRectChanged()
		{
			if (this.owner != null && this.AllowOutlining)
			{
				this.owner.Invalidate();
			}
		}
		protected virtual void OnImageSizeChanged()
		{
			if (this.owner != null && this.AllowOutlining)
			{
				this.owner.Invalidate();
			}
		}
		public Outlining(CodeEditor owner)
		{
			this.owner = owner;
			if (owner != null)
			{
				this.displayLines = owner.DisplayLines;
			}
		}
		public bool ShouldSerializeOutlineColor()
		{
			return this.outlineColor != EditConsts.DefaultOutlineForeColor;
		}
		public bool ShouldSerializeOutlineOptions()
		{
			return this.OutlineOptions != EditConsts.DefaultOutlineOptions;
		}
		public virtual void Assign(Outlining source)
		{
			this.AllowOutlining = source.AllowOutlining;
			this.OutlineOptions = source.OutlineOptions;
			this.OutlineColor = source.OutlineColor;
		}
		public virtual void OutlineText()
		{
			if (this.AllowOutlining && this.owner != null && this.owner.Source.NeedOutlineText())
			{
				SyntaxParser syntaxParser = (SyntaxParser)this.owner.Source.Lexer;
				syntaxParser.Strings = this.owner.Lines;
				syntaxParser.ReparseText();
				List<Range> ranges = new List<Range>();
				syntaxParser.Outline(ranges);
				this.SetOutlineRanges(ranges, true);
			}
		}
		public virtual void UnOutlineText()
		{
			if (this.displayLines != null)
			{
				this.displayLines.UnOutline();
			}
		}
		public virtual void ResetOutlineColor()
		{
			this.OutlineColor = EditConsts.DefaultOutlineForeColor;
		}
		public virtual OutlineRange Outline(int first, int last, int level)
		{
			return (this.displayLines != null) ? this.displayLines.Outline(first, last, level) : null;
		}
		public virtual OutlineRange Outline(int first, int last)
		{
			return (this.displayLines != null) ? this.displayLines.Outline(first, last) : null;
		}
		public virtual OutlineRange Outline(Point startPoint, Point endPoint, int level)
		{
			return (this.displayLines != null) ? this.displayLines.Outline(startPoint, endPoint, level) : null;
		}
		public virtual OutlineRange Outline(Point startPoint, Point endPoint)
		{
			return (this.displayLines != null) ? this.displayLines.Outline(startPoint, endPoint) : null;
		}
		public virtual OutlineRange Outline(int first, int last, int level, string outlineText)
		{
			return (this.displayLines != null) ? this.displayLines.Outline(first, last, level, outlineText) : null;
		}
		public virtual OutlineRange Outline(int first, int last, string outlineText)
		{
			return (this.displayLines != null) ? this.displayLines.Outline(first, last, outlineText) : null;
		}
		public virtual OutlineRange Outline(Point startPoint, Point endPoint, int level, string outlineText)
		{
			return (this.displayLines != null) ? this.displayLines.Outline(startPoint, endPoint, level, outlineText) : null;
		}
		public virtual OutlineRange Outline(Point startPoint, Point endPoint, string outlineText)
		{
			return (this.displayLines != null) ? this.displayLines.Outline(startPoint, endPoint, outlineText) : null;
		}
		public virtual void UnOutline(Point position)
		{
			if (this.displayLines != null)
			{
				this.displayLines.UnOutline(position);
			}
		}
		public virtual void UnOutline(int index)
		{
			if (this.displayLines != null)
			{
				this.displayLines.UnOutline(index);
			}
		}
		public virtual void UnOutline()
		{
			if (this.displayLines != null)
			{
				this.displayLines.UnOutline();
			}
		}
		public virtual OutlineRange GetOutlineRange(Point position)
		{
			return (this.displayLines != null) ? this.displayLines.GetOutlineRange(position) : null;
		}
		public virtual OutlineRange GetOutlineRange(int index)
		{
			return (this.displayLines != null) ? this.displayLines.GetOutlineRange(index) : null;
		}
		public virtual bool IsExpanded(int index)
		{
			return this.displayLines != null && this.displayLines.IsExpanded(index);
		}
		public virtual bool IsCollapsed(int index)
		{
			return this.displayLines != null && this.displayLines.IsCollapsed(index);
		}
		public virtual bool IsVisible(Point position)
		{
			return this.displayLines == null || this.displayLines.IsVisible(position);
		}
		public virtual bool IsVisible(int index)
		{
			return this.displayLines == null || this.displayLines.IsVisible(index);
		}
		public virtual void Collapse(int index)
		{
			if (this.displayLines != null)
			{
				this.displayLines.Collapse(index);
			}
		}
		public virtual void Expand(int index)
		{
			if (this.displayLines != null)
			{
				this.displayLines.Expand(index);
			}
		}
	
		public virtual void EnsureExpanded(Point position)
		{
			if (this.displayLines != null)
			{
				this.displayLines.EnsureExpanded(position);
			}
		}
	
		public virtual void ToggleOutlining()
		{
			if (this.displayLines != null)
			{
				this.displayLines.ToggleOutlining();
			}
		}
	
		public virtual void CollapseToDefinitions()
		{
			if (this.displayLines != null)
			{
				this.displayLines.CollapseToDefinitions();
			}
		}
	
		public virtual int GetOutlineRanges(IList<Range> ranges, int index)
		{
			return (this.displayLines != null) ? this.displayLines.GetOutlineRanges(ranges, index) : 0;
		}
	
		public virtual bool CanExpand(int line)
		{
			return this.displayLines == null || this.displayLines.CanExpand(line);
		}
		public virtual bool CanCollapse(int line)
		{
			return this.displayLines == null || this.displayLines.CanCollapse(line);
		}
		public virtual void SetOutlineRanges(List<Range> ranges, bool preserveVisible)
		{
			if (this.displayLines != null)
			{
				this.displayLines.SetOutlineRanges(ranges, preserveVisible);
			}
		}
		public virtual int BeginUpdate()
		{
			return (this.displayLines != null) ? this.displayLines.BeginUpdate() : 0;
		}
		public virtual int EndUpdate()
		{
			return (this.displayLines != null) ? this.displayLines.EndUpdate() : 0;
		}
		public virtual void ResetAllowOutlining()
		{
			this.AllowOutlining = false;
		}
		public virtual void ResetOutlineOptions()
		{
			this.OutlineOptions = EditConsts.DefaultOutlineOptions;
		}
	}
}
